package com.c2soft.ncmxBtrade.controller;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Random;

import javax.annotation.PostConstruct;

import lombok.extern.log4j.Log4j2;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.concurrent.ConcurrentTaskScheduler;
import org.springframework.stereotype.Controller;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;






import com.c2soft.ncmxBtrade.domain.Heading;

@Log4j2
@Controller
public class HeadingWebSocketController {

	@Autowired
	private SimpMessagingTemplate template;

	private TaskScheduler scheduler = new ConcurrentTaskScheduler();
	
	private List<Heading> Headings = new ArrayList<Heading>();

	private enum Symbols {
		GOLD_L, SILVER_L,ZINC_L,COPPER_L,COPPER_S,ALUMINIUM_L,ALUMINIUM_S,BRCRUDE_OIL,CRUDE_OIL,GOLD_S,
		LEAD_L,LEAD_S,NATURAL_GAS,SILVER_S,ZINC_S,NICKEL_L,NICKEL_S;
		
		
		private static final List<Symbols> VALUES = Collections
				.unmodifiableList(Arrays.asList(values()));
		
		private static final int SIZE = VALUES.size();
		
		private static final Random RANDOM = new Random();

		public static Symbols randomSymbol() {
			return VALUES.get(RANDOM.nextInt(SIZE));
		}
		
	};
	
	private String getRandomDoubleInRange(double min,double max){
		double random = new Random().nextDouble();
		double result = min + (random * (max - min));
		return String.valueOf(result);
	}
	
	private String getRandomIntInRange(int min,int max){
		int random = new Random().nextInt();
		int result = min + (random * (max - min));
		return String.valueOf(result);
	}

	/**
	 * Iterates stock list, update the price by randomly choosing a positive or
	 * negative percentage, then broadcast it to all subscribing clients
	 */
	private void updatePriceAndBroadcast() {
		if(CollectionUtils.isEmpty(Headings)){
			Headings.add(getAnyRandomHeadingForSymbol(Symbols.COPPER_S.toString()));
			Headings.add(getAnyRandomHeadingForSymbol(Symbols.COPPER_L.toString()));
			Headings.add(getAnyRandomHeadingForSymbol(Symbols.ZINC_L.toString()));
			Headings.add(getAnyRandomHeadingForSymbol(Symbols.SILVER_L.toString()));
			Headings.add(getAnyRandomHeadingForSymbol(Symbols.GOLD_L.toString()));
			Headings.add(getAnyRandomHeadingForSymbol(Symbols.ALUMINIUM_L.toString()));
			Headings.add(getAnyRandomHeadingForSymbol(Symbols.ALUMINIUM_S.toString()));
			Headings.add(getAnyRandomHeadingForSymbol(Symbols.BRCRUDE_OIL.toString()));
			Headings.add(getAnyRandomHeadingForSymbol(Symbols.CRUDE_OIL.toString()));
			Headings.add(getAnyRandomHeadingForSymbol(Symbols.GOLD_S.toString()));
			Headings.add(getAnyRandomHeadingForSymbol(Symbols.LEAD_L.toString()));
			Headings.add(getAnyRandomHeadingForSymbol(Symbols.LEAD_S.toString()));
			Headings.add(getAnyRandomHeadingForSymbol(Symbols.NATURAL_GAS.toString()));
			Headings.add(getAnyRandomHeadingForSymbol(Symbols.SILVER_S.toString())); 
			Headings.add(getAnyRandomHeadingForSymbol(Symbols.ZINC_S.toString()));
			Headings.add(getAnyRandomHeadingForSymbol(Symbols.NICKEL_L.toString()));
			Headings.add(getAnyRandomHeadingForSymbol(Symbols.NICKEL_S.toString())); 
			Headings.add(getAnyRandomHeadingForContentId(Symbols.COPPER_S.toString()));
			Headings.add(getAnyRandomHeadingForContentId(Symbols.COPPER_L.toString()));
			Headings.add(getAnyRandomHeadingForContentId(Symbols.ZINC_L.toString()));
			Headings.add(getAnyRandomHeadingForContentId(Symbols.SILVER_L.toString()));
			Headings.add(getAnyRandomHeadingForContentId(Symbols.GOLD_L.toString()));
			Headings.add(getAnyRandomHeadingForContentId(Symbols.ALUMINIUM_L.toString()));
			Headings.add(getAnyRandomHeadingForContentId(Symbols.ALUMINIUM_S.toString()));
			Headings.add(getAnyRandomHeadingForContentId(Symbols.BRCRUDE_OIL.toString()));
			Headings.add(getAnyRandomHeadingForContentId(Symbols.CRUDE_OIL.toString()));
			Headings.add(getAnyRandomHeadingForContentId(Symbols.GOLD_S.toString()));
			Headings.add(getAnyRandomHeadingForContentId(Symbols.LEAD_L.toString()));
			Headings.add(getAnyRandomHeadingForContentId(Symbols.LEAD_S.toString()));
			Headings.add(getAnyRandomHeadingForContentId(Symbols.NATURAL_GAS.toString()));
			Headings.add(getAnyRandomHeadingForContentId(Symbols.SILVER_S.toString())); 
			Headings.add(getAnyRandomHeadingForContentId(Symbols.ZINC_S.toString()));
			Headings.add(getAnyRandomHeadingForContentId(Symbols.NICKEL_L.toString()));
			Headings.add(getAnyRandomHeadingForContentId(Symbols.NICKEL_S.toString())); 
	}
		
		int i = 0;	
		for (Heading Heading : Headings) {
			if(i<17){	
			Heading = getAnyRandomHeadingForSymbol(Heading.getSymbol());		
			Headings.set(i, Heading);
			}
			if(i>=17 && i<34){				
			Heading = getAnyRandomHeadingForContentId(Heading.getSymbol());
			Headings.set(i, Heading);
			}
			i++;
		
		
		}			
		template.convertAndSend("/topic/Heading", Headings);
	}

	/**
	 * Invoked after bean creation is complete, this method will schedule
	 * updatePriceAndBroacast every 1 second
	 */
	@PostConstruct
	private void broadcastTimePeriodically() {
		scheduler.scheduleAtFixedRate(new Runnable() {
			@Override
			public void run() {
				updatePriceAndBroadcast();
			}
		}, 800);
	}
	
	

	/**
	 * Handler to add one stock
	 */
	@MessageMapping("/addStocks")
	public void addStock() throws Exception {
	
		Headings.add(getAnyRandomHeading());
		updatePriceAndBroadcast();
	}

	/**
	 * Handler to remove all stocks
	 */
	@MessageMapping("/removeAlls")
	public void removeAllStocks() {
		Headings.clear();
		updatePriceAndBroadcast();
	}

	/**
	 * Serve the main page
	 */
	@RequestMapping(value = "/headWebSocket", method = RequestMethod.GET)
	public String headWebSckt() {

		return "HeadWebSckt";
	}
	
	
	private Heading getAnyRandomHeading(){
		String l_prev_Close = getRandomDoubleInRange(100,1000);
		String l_symbol = Symbols.randomSymbol().toString();
		String l_ask_Qty="5";
		String l_contentId="31Jul2014";
		String l_bid_Rate=getRandomIntInRange(1,5);
		String l_ask_Rate=getRandomIntInRange(1,10);
		String l_bid_Qty="1";
		String l_netChange=getRandomIntInRange(1,10);
		String l_open=getRandomIntInRange(1,10);
		String l_high=getRandomIntInRange(1,10);
		String l_low=getRandomIntInRange(1,10);
		String l_ltp=getRandomIntInRange(1,10);
		String l_perChange=getRandomIntInRange(1,10);
		String l_atp=getRandomIntInRange(1,10);
		String l_dpr=getRandomIntInRange(1,10);
		String l_voll=getRandomIntInRange(1,10);
		String l_trend=getRandomIntInRange(1,10);
	    String l_lth=getRandomIntInRange(1,10);
		String l_ltl=getRandomIntInRange(1,10);

		//updating Heading
		return Heading.builder().ask_Qty(l_ask_Qty).bid_Rate(l_bid_Rate).contentId(l_contentId)
				.prev_Close(l_prev_Close).ask_Rate(l_ask_Rate).bid_Qty(l_bid_Qty).netChange(l_netChange).open(l_open)
				.symbol(l_symbol).high(l_high).low(l_low).ltp(l_ltp).perChange(l_perChange).atp(l_atp)
				.dpr(l_dpr).voll(l_voll).trend(l_trend).lth(l_lth).ltl(l_ltl).build();
	}
	
	private Heading getAnyRandomHeadingForSymbol(String symbol){
		String instrId="0000";
		if(symbol.equals(Symbols.COPPER_S.toString())){
			instrId="1001";
		}
		if(symbol.equals(Symbols.COPPER_L.toString())){
			instrId="1002";
		}
		if(symbol.equals(Symbols.ZINC_L.toString())){
			instrId="1003";
		}
		if(symbol.equals(Symbols.SILVER_L.toString())){
			instrId="1004";
		}
		if(symbol.equals(Symbols.GOLD_L.toString())){
			instrId="1005";
		}
		if(symbol.equals(Symbols.ALUMINIUM_L.toString())){
			instrId="1006";
		}
		if(symbol.equals(Symbols.ALUMINIUM_S.toString())){
			instrId="1007";
		}
		if(symbol.equals(Symbols.BRCRUDE_OIL.toString())){
			instrId="1008";
		}
		if(symbol.equals(Symbols.CRUDE_OIL.toString())){
			instrId="1009";
		}
		if(symbol.equals(Symbols.GOLD_S.toString())){
			instrId="1010";
		}
		if(symbol.equals(Symbols.LEAD_L.toString())){
			instrId="1011";
		}
		if(symbol.equals(Symbols.LEAD_S.toString())){
			instrId="1012";
		}
		if(symbol.equals(Symbols.NATURAL_GAS.toString())){
			instrId="1013";
		}
		if(symbol.equals(Symbols.SILVER_S.toString())){
			instrId="1014";
		}
		if(symbol.equals(Symbols.ZINC_S.toString())){
			instrId="1015";
		}
		if(symbol.equals(Symbols.NICKEL_L.toString())){
			instrId="1016";
		}
		if(symbol.equals(Symbols.NICKEL_S.toString())){
			instrId="1017";
		}
		String l_prev_Close = getRandomDoubleInRange(100,1000);
		String l_symbol =symbol;
		String l_ask_Qty="5";
		String l_contentId="30Aug2014";
		String l_bid_Rate=getRandomIntInRange(1,10);
		String l_ask_Rate=getRandomIntInRange(1,10);
		String l_bid_Qty="1";
		String l_netChange=getRandomIntInRange(1,10);
		String l_open=getRandomIntInRange(1,10);
		String l_high=getRandomIntInRange(1,10);
		String l_low=getRandomIntInRange(1,10);
		String l_ltp=getRandomIntInRange(1,10);
		String l_perChange=getRandomIntInRange(1,10);
		String l_atp=getRandomIntInRange(1,10);
		String l_dpr=getRandomIntInRange(1,10);
		String l_voll=getRandomIntInRange(1,10);
		String l_trend=getRandomIntInRange(1,10);
	    String l_lth=getRandomIntInRange(1,10);
		String l_ltl=getRandomIntInRange(1,10);
		//updating Heading
		return Heading.builder().ask_Qty(l_ask_Qty).bid_Rate(l_bid_Rate).contentId(l_contentId)
				.prev_Close(l_prev_Close).ask_Rate(l_ask_Rate).bid_Qty(l_bid_Qty).netChange(l_netChange).open(l_open)
				.symbol(l_symbol).high(l_high).low(l_low).ltp(l_ltp).perChange(l_perChange).atp(l_atp)
				.dpr(l_dpr).voll(l_voll).trend(l_trend).lth(l_lth).ltl(l_ltl).instId(instrId).build();
	}
	
	private Heading getAnyRandomHeadingForContentId(String symbol){
		String instrId="0000";
		if(symbol.equals(Symbols.COPPER_S.toString())){
			instrId="1001";
		}
		if(symbol.equals(Symbols.COPPER_L.toString())){
			instrId="1002";
		}
		if(symbol.equals(Symbols.ZINC_L.toString())){
			instrId="1003";
		}
		if(symbol.equals(Symbols.SILVER_L.toString())){
			instrId="1004";
		}
		if(symbol.equals(Symbols.GOLD_L.toString())){
			instrId="1005";
		}
		if(symbol.equals(Symbols.ALUMINIUM_L.toString())){
			instrId="1006";
		}
		if(symbol.equals(Symbols.ALUMINIUM_S.toString())){
			instrId="1007";
		}
		if(symbol.equals(Symbols.BRCRUDE_OIL.toString())){
			instrId="1008";
		}
		if(symbol.equals(Symbols.CRUDE_OIL.toString())){
			instrId="1009";
		}
		if(symbol.equals(Symbols.GOLD_S.toString())){
			instrId="1010";
		}
		if(symbol.equals(Symbols.LEAD_L.toString())){
			instrId="1011";
		}
		if(symbol.equals(Symbols.LEAD_S.toString())){
			instrId="1012";
		}
		if(symbol.equals(Symbols.NATURAL_GAS.toString())){
			instrId="1013";
		}
		if(symbol.equals(Symbols.SILVER_S.toString())){
			instrId="1014";
		}
		if(symbol.equals(Symbols.ZINC_S.toString())){
			instrId="1015";
		}
		if(symbol.equals(Symbols.NICKEL_L.toString())){
			instrId="1016";
		}
		if(symbol.equals(Symbols.NICKEL_S.toString())){
			instrId="1017";
		}
		String l_prev_Close = getRandomDoubleInRange(100,1000);
		String l_symbol =symbol;
		String l_ask_Qty="5";
		String l_contentId="30Sep2014";
		String l_bid_Rate=getRandomIntInRange(1,10);
		String l_ask_Rate=getRandomIntInRange(1,10);
		String l_bid_Qty="1";
		String l_netChange=getRandomIntInRange(1,10);
		String l_open=getRandomIntInRange(1,10);
		String l_high=getRandomIntInRange(1,10);
		String l_low=getRandomIntInRange(1,10);
		String l_ltp=getRandomIntInRange(1,10);
		String l_perChange=getRandomIntInRange(1,10);
		String l_atp=getRandomIntInRange(1,10);
		String l_dpr=getRandomIntInRange(1,10);
		String l_voll=getRandomIntInRange(1,10);
		String l_trend=getRandomIntInRange(1,10);
	    String l_lth=getRandomIntInRange(1,10);
		String l_ltl=getRandomIntInRange(1,10);
		//updating Heading
		return Heading.builder().ask_Qty(l_ask_Qty).bid_Rate(l_bid_Rate).contentId(l_contentId)
				.prev_Close(l_prev_Close).ask_Rate(l_ask_Rate).bid_Qty(l_bid_Qty).netChange(l_netChange).open(l_open)
				.symbol(l_symbol).high(l_high).low(l_low).ltp(l_ltp).perChange(l_perChange).atp(l_atp)
				.dpr(l_dpr).voll(l_voll).trend(l_trend).lth(l_lth).ltl(l_ltl).instId(instrId).build();
	}
	
}
